package com.example.rbac.service.impl;
import com.example.rbac.pojo.SysRole;
import com.example.rbac.pojo.SysUser;
import com.example.rbac.repository.SysPermissionRepository;
import com.example.rbac.repository.SysUserRepository;
import com.example.rbac.service.RbacService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.util.AntPathMatcher;
import javax.servlet.http.HttpServletRequest;
import java.util.HashSet;
import java.util.Set;
//将用户的角色信息，权限信息等进行适配，当用户执行操作的时候，对其操作进行权限判断
@Service
@Component("rbacService")
public class RbacServiceImpl implements RbacService {
    @Autowired
    private SysPermissionRepository sysPermissionRepository;
    @Autowired
    private SysUserRepository sysUserRepository;
    private AntPathMatcher antPathMatcher=new AntPathMatcher();
    /*
    *实现rbac接口 重写hashPermission用于判断当前用户的权限信息
    * 这里应该注入用户和该用户所拥有的权限（权限在登录成功的时候已经保存起来，
       当需要访问该用户的权限的时候，直接从缓存中取出）
    *然后验证该请求是否有权限，有就返回true，否则返回false，不允许访问该url
    *还传入了request ,可以使用request获取该次请求的类型
    *根据restful风格使用他来控制我们的权限
    *例如当这个请求时Post请求，证明该请求是向服务器发送一个新建资源请求
    * 我们可以使用request.getMethod()来获取该请求的方式，然后在配合角色所允许的权限路径进行判断
      和授权操！
    *如果能获取到Principal对象不为空证明，授权已经通过
     */

    @Override
    public boolean hasPermission(HttpServletRequest request, Authentication authentication) {
        //获取用户认证信息
        Object principal=authentication.getPrincipal();
        boolean hasPermission=false;
        //判断数据是否为空 ，以及类型是否正确
        if(null!=principal&&principal instanceof UserDetails){
            String username=((UserDetails) principal).getUsername();
            //用户的url权限
            Set<String> urls=new HashSet<>();
            //保存用户的资源权限
            Set<String> curds=new HashSet<>();
            SysUser sysUser=sysUserRepository.findByName(username);
            //通过获取的认证信息，将用户的url权限以及资源权限进行封装
            for(SysRole role:sysUser.getRoles()){
                role.getPermissions().forEach(sysPermission -> {
                    urls.add(sysPermission.getUrl());
                });
            }
            //通过实际的url和保存的允许访问的url权限进行比对
            for(String url:urls){
                if(antPathMatcher.match(url,request.getRequestURI())){
                    hasPermission=true;
                    break;
                }
            }
        }
        return hasPermission;
    }
}
